﻿using Microsoft.Web.Administration;
using Microsoft.Win32;
using QuickManager.Code.SiteMgr.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace QuickManager.Code.SiteMgr
{
    public class SiteManager
    {
        static string DataDir = AppDomain.CurrentDomain.BaseDirectory + "/Data";
        static string DataXml = AppDomain.CurrentDomain.BaseDirectory + "Data/SiteData.xml";
        static XmlDocument document = new XmlDocument();
        static SiteManager()
        {
            if (File.Exists(DataXml) == false)
            {
                Directory.CreateDirectory(DataDir);   //创建目录
                XmlElement root = document.CreateElement("SiteData");
                document.AppendChild(root);
                document.Save(DataXml); //保存XML内容
            }
        }

        /// <summary>
        /// 注册数据库注册表
        /// </summary>
        /// <param name="path"></param>
        static void RegistRegFile(string path)
        {
            //注册表配置
            RegistryKey regClassesRoot = Registry.ClassesRoot;
            RegistryKey regFile = regClassesRoot.OpenSubKey("regfile", true);
            RegistryKey regShell = regFile.OpenSubKey("shell", true);
            RegistryKey regOpen = regShell.OpenSubKey("open", true);
            RegistryKey regCommand = regOpen.OpenSubKey("command", true);
            regCommand.SetValue("", "regedit.exe /s" + '"' + "%1" + '"');    //默认值的名称为空

            try
            {
                Process.Start("regedit", string.Format(" /s {0}", path)).WaitForExit();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                //还原注册表配置
                regCommand.SetValue("", "regedit.exe " + '"' + "%1" + '"');
            }

        }

        static void UpdateLicence(string webRoot, string registerName)
        {
            try
            {
                //去只读
                File.SetAttributes(webRoot + "/bin/License.xml", FileAttributes.Normal);

                //修改Lincence
                XmlDocument license = new XmlDocument();
                license.Load(webRoot + "/bin/License.xml");
                license.SelectSingleNode("license/data/product/dbconns/dbconn[@appname='Default']").Attributes["regname"].Value = registerName;
                license.Save(webRoot + "/bin/License.xml");
            }
            catch
            {
                //throw new Exception("更新License数据库信息异常", ex);
            }
        }

        /// <summary>
        /// 读取Licence中配置的注册表名称
        /// </summary>
        /// <param name="webRoot"></param>
        /// <returns></returns>
        static string GetRegisterName(string webRoot)
        {

            try
            {
                XmlDocument license = new XmlDocument();
                license.Load(webRoot + "/bin/License.xml");
                return license.SelectSingleNode("license/data/product/dbconns/dbconn[@appname='Default']").Attributes["regname"].Value;
            }
            catch
            {
                //throw new Exception("更新License数据库信息异常", ex);
                return "Licence节点读取错误";
            }
        }

        public static List<string> GetRegisterNameList()
        {
            try
            {
                return Environment.Is64BitOperatingSystem
                    ? Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Mysoft").GetSubKeyNames().ToList()
                    : Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Mysoft").GetSubKeyNames().ToList();
            }
            catch
            {
                return new List<string>();
            }
        }

        /// <summary>
        /// 初始化方式新建站点
        /// </summary>
        /// <param name="siteView"></param>
        /// <returns>站点ID</returns>
        public static string CraeteSite(SiteInfoModel siteInfo)
        {
            ServerManager SvrMgr = new ServerManager();
            using (SQLiteDataContext context = DB.GetContext())
            {
                //保存数据库
                siteInfo.SiteID = string.IsNullOrEmpty(siteInfo.SiteID) ? Guid.NewGuid().ToString() : siteInfo.SiteID;
                SiteInfoModel oldSiteInfo = GetSiteInfo(siteInfo.SiteID);
                try
                {
                    if (oldSiteInfo != null)
                    {
                        //删除旧的站点和应用程序池
                        Site site = SvrMgr.Sites.FirstOrDefault<Site>(m => m.Name == oldSiteInfo.SiteName);
                        if (site != null)
                        {
                            IISMenager.DeleteWebSite(site.Name);
                        }
                    }
                }
                catch
                {
                }

                if (oldSiteInfo == null)
                {
                    //新建
                    context.GetTable<SiteInfoModel>().InsertOnSubmit(siteInfo);
                    context.SubmitChanges();
                }
            }
            return siteInfo.SiteID;
        }

        /// <summary>
        /// 保存编辑的站点信息
        /// </summary>
        /// <param name="siteInfoView"></param>
        /// <returns></returns>
        public static void SaveEditSite(SiteInfoView siteInfoView)
        {
            //创建注册表
            if (string.IsNullOrEmpty(siteInfoView.SiteInfo.RegisterName) == false)
            {
                string registerText = string.Empty;
                //读取嵌入式资源
                Assembly asm = Assembly.GetExecutingAssembly();
                foreach (string resourceName in new string[] {
                    "QuickManager.Res.数据库配置x32.reg",
                    "QuickManager.Res.数据库配置x64.reg" })
                {
                    using (Stream stream = asm.GetManifestResourceStream(resourceName))
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            registerText = streamReader.ReadToEnd();
                        }
                    }
                    registerText = string.Format(registerText,
                        siteInfoView.DBInfo.RegisterName,
                        siteInfoView.DBInfo.Address.Replace("\\", "\\\\"),
                        siteInfoView.DBInfo.DBName,
                        siteInfoView.DBInfo.UserName,
                        siteInfoView.DBInfo.Passoword);
                    try
                    {
                        File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "template.reg", registerText);
                        RegistRegFile(AppDomain.CurrentDomain.BaseDirectory + "template.reg");
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("更新注册表异常", ex);
                    }
                    finally
                    {
                        if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "template.reg"))
                        {
                            File.Delete(AppDomain.CurrentDomain.BaseDirectory + "template.reg");
                        }
                    }
                }
                //更新Licence数据库注册表
                UpdateLicence(siteInfoView.SiteInfo.LocalPath, siteInfoView.SiteInfo.RegisterName);
            }
            //创建IIS站点
            IISMenager.CreateWebSite(siteInfoView.SiteInfo);

            using (SQLiteDataContext context = DB.GetContext())
            {
                //更新数据库信息
                SiteInfoModel siteInfo = context.GetTable<SiteInfoModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteInfoView.SiteInfo.SiteID);
                siteInfo.ToUpdateModel(siteInfoView.SiteInfo);

                //更新或新增挂接的需求文档
                LinkRequireModel reqInfo = context.GetTable<LinkRequireModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteInfo.SiteID);
                if (reqInfo == null)
                {
                    siteInfoView.RequireInfo.LinkID = Guid.NewGuid().ToString();
                    context.GetTable<LinkRequireModel>().InsertOnSubmit(siteInfoView.RequireInfo);
                }
                else
                {
                    reqInfo.RequireCode = siteInfoView.RequireInfo.RequireCode;
                }

                context.SubmitChanges();
            }
        }

        /// <summary>
        /// 从IIS初始化的站点
        /// </summary>
        public static void InitSiteFromIIS()
        {
            ServerManager SvrMgr = new ServerManager();
            List<Site> iisSites = SvrMgr.Sites.ToList();    //IIS站点信息
            List<SiteInfoModel> dbSites = SiteManager.GetSiteList();    //数据库站点信息

            //删除数据库中存在，但IIS中不存在的站点
            List<SiteInfoModel> delSites = dbSites
                .Where(m => iisSites.Exists(d => d.Name.Equals(m.SiteName, StringComparison.OrdinalIgnoreCase)) == false)
                .ToList();

            //增加数据库中不存在，但IIS中存在的站点
            List<Site> newSites = iisSites
                .Where(m => dbSites.Exists(d => d.SiteName.Equals(m.Name, StringComparison.OrdinalIgnoreCase)) == false)
                .ToList();
            List<SiteInfoModel> newDbSites = new List<SiteInfoModel>();
            foreach (Site st in newSites)
            {
                newDbSites.Add(new SiteInfoModel()
                {
                    SiteID = Guid.NewGuid().ToString(),
                    GroupID = Guid.Empty.ToString(),
                    SiteName = st.Name,
                    LocalPath = IISMenager.GetPhysicalPath(st),
                    Port = IISMenager.GetDefaultPort(st),
                    PoolType = IISMenager.GetPoolType(st),
                    NetVersion = IISMenager.GetNetVersion(st),
                    RegisterName = GetRegisterName(IISMenager.GetPhysicalPath(st))
                });
            }

            using (SQLiteDataContext context = DB.GetContext())
            {
                //删除数据库
                foreach (var item in delSites)
                {
                    var site = context.GetTable<SiteInfoModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == item.SiteID);
                    if (site != null)
                    {
                        context.GetTable<SiteInfoModel>().DeleteOnSubmit(site);
                    }
                }

                //保存数据库
                context.GetTable<SiteInfoModel>().InsertAllOnSubmit(newDbSites);

                //提交事务
                context.SubmitChanges();
            }
        }

        /// <summary>
        /// 取站点信息
        /// </summary>
        /// <param name="siteID"></param>
        /// <returns></returns>
        public static SiteInfoView GetSiteView(string siteID)
        {
            using (SQLiteDataContext context = DB.GetContext())
            {
                SiteInfoModel siteInfo = context.GetTable<SiteInfoModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteID);
                DBInfoModel dbInfo = GetDBInfo(siteInfo.RegisterName);
                LinkRequireModel reqInfo = context.GetTable<LinkRequireModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteInfo.SiteID) ?? new LinkRequireModel();
                return new SiteInfoView()
                {
                    SiteInfo = siteInfo,
                    DBInfo = dbInfo,
                    RequireInfo = reqInfo
                };
            }
        }


        public static SiteInfoModel GetSiteInfo(string siteID)
        {
            using (SQLiteDataContext context = DB.GetContext())
            {
                SiteInfoModel siteInfo = context.GetTable<SiteInfoModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteID);
                return siteInfo;
            }
        }

        public static DBInfoModel GetDBInfo(string registerName)
        {
            RegistryKey regKey = Environment.Is64BitOperatingSystem
                ? Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Mysoft\" + registerName)
                : Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Mysoft" + registerName);
            return (string.IsNullOrWhiteSpace(registerName) || regKey == null)
                ? new DBInfoModel()
                {
                    RegisterName = registerName
                }
                : new DBInfoModel()
                {
                    RegisterName = registerName,
                    Address = regKey.GetValue("ServerName").ToString(),
                    DBName = regKey.GetValue("DBName").ToString(),
                    UserName = regKey.GetValue("UserName").ToString(),
                    Passoword = regKey.GetValue("SaPassword").ToString()
                };
        }

        /// <summary>
        /// 查询所有站点
        /// </summary>
        /// <returns></returns>
        public static List<SiteInfoModel> GetSiteList()
        {
            List<SiteInfoModel> sites = new List<SiteInfoModel>();
            using (SQLiteDataContext context = DB.GetContext())
            {
                sites = context.GetTable<SiteInfoModel>()
                    .ToList()
                    .OrderBy(m => m.SiteName)
                    .ToList();
            }
            return sites;
        }

        public static void DeleteSite(string siteID)
        {
            using (SQLiteDataContext context = DB.GetContext())
            {
                SiteInfoModel siteInfo = context.GetTable<SiteInfoModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteID);
                LinkRequireModel reqInfo = context.GetTable<LinkRequireModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteID);

                //删除IIS
                IISMenager.DeleteWebSite(siteInfo.SiteName);

                //删除数据库
                context.GetTable<SiteInfoModel>().DeleteOnSubmit(siteInfo);
                if (reqInfo != null)
                {
                    //删除挂接需求
                    context.GetTable<LinkRequireModel>().DeleteOnSubmit(reqInfo);
                }
                context.SubmitChanges();
            }
        }

        public static void ChangeGroup(string siteID, string groupID)
        {

            using (SQLiteDataContext context = DB.GetContext())
            {
                SiteInfoModel siteInfo = context.GetTable<SiteInfoModel>()
                    .ToList()
                    .FirstOrDefault(m => m.SiteID == siteID);
                siteInfo.GroupID = groupID;
                context.SubmitChanges();
            }
        }
    }
}
